/**
 * \file VcuComm_messages.c
 * \copyright UDAN Co.,Ltd. *
 *
 * \brief 整车通信报文文件.
 *
 * * \par 修订历史:
 * | 版本号 | 修订日志 | 修改人 | 修订时间 |
 * | :--- | :--- | :--- | :--- |
 * | 0.1 | 初始版本, 完成讨论部分的定义. | UD00004 | 20170316 |
 */
#include "App_Types.h"
#include "Cpu.h"
#include "Det.h"
#include "VcuComm_Types.h"
#include "VcuComm_Messages.h"
#include "CurrentM.h"
#include "Statistic.h"
#include "Soc.h"
#include "Soh.h"
#include "Insu.h"
#include "ChargeConnectM.h"
#include "ChargerComm.h"
#include "HWDiagnosis.h"
#include "AppInfo.h"
#include "ParameterM.h"
#include "CellDataM.h"
#include "RelayM.h"
#include "RelayM_Lcfg.h"
#include "ChargeM.h"
#include "BalanceM.h"
#include "PowerM.h"
#include "PrechargeM.h"
#include "UserStrategy.h"
#include "DischargeM.h"

#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
#include "Modules.h"
#endif

#define VCUCOMM_MESSAGES_E_PARAM_INVALID_PTR            0U

#define VCUCOMM_MESSAGES_API_ID_ReceiveCbk              0U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x1E1Cbk 1U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x1E4Cbk 2U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F5Cbk 3U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F3Cbk 4U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x211Cbk 5U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x351Cbk 6U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x352Cbk 7U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x353Cbk 8U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x354Cbk 9U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x355Cbk 10U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x356Cbk 11U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x357Cbk 12U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F3Cbk 13U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F4Cbk 14U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F5Cbk 15U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F6Cbk 16U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x3FFCbk 17U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F4Cbk 18U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x201Cbk 19U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x360Cbk 21U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x361Cbk 22U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x358Cbk 23U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x202Cbk 24U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x203Cbk 25U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x204Cbk 26U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x205Cbk 27U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x206Cbk 28U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x207Cbk 29U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x208Cbk 30U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x390Cbk 31U
#define VCUCOMM_MESSAGES_API_ID_GetMsgData0x391Cbk 32U


#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
#define VALIDATE_PTR(_ptr, _api) \
    if (_ptr == NULL) { \
        Det_ReportError(MODULE_ID_VCUCOMM_MESSAGES, 0U, _api, VCUCOMM_MESSAGES_E_PARAM_INVALID_PTR); \
        goto cleanup; \
    }
#else
#define VALIDATE_PTR(_ptr, _api)
#endif

#define VCUCOMM_CURRENT_OFFSET      (-10000)
#define VCUCOMM_VOLT_4_DISPLAY(volt)    (VOLT_4_DISPLAY(volt) < 10000U ? VOLT_4_DISPLAY(volt) : 10000U)
#define TEMP_TO_50_OFFSET(VALUE)        (CellDataM_TemperatureIsValid((uint16)(VALUE)) ? ((VALUE) >= -50U ? ((VALUE) - 50U) : 0U) : (VALUE))

VcuComm_MsgDataType VcuComm_MsgData;

static uint16 VcuComm_bms2VcuCurrent(Current_CurrentType current);

void VcuComm_MessageInit(Async_LooperType *looper)
{
    VcuComm_MsgData.PowerCommand = VCUCOMM_POWER_OFF;
    (void)looper;
    (void)VcuComm_SendIPduRegister(&VcuComm_IPduSendConfigInfo[0], VcuComm_SendIPduNum);
}

void VcuComm_GetMsgData0x1E1Cbk(uint8 *Buffer, uint16 *Length)
{
    Current_CurrentType current;
    uint16 index = 0U, temp;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1E1Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1E1Cbk);
    /**< 总压 */
    temp = Statistic_GetBcu100mvTotalVoltage();
    temp = Statistic_TotalVoltageIsValid(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 总电流 */
    current = CurrentM_GetCurrentCalibrated(CURRENTM_CHANNEL_MAIN);
    temp = VcuComm_bms2VcuCurrent(current);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 真实SOC */
    WRITE_BT_UINT16(Buffer, index,  Soc_Get());
    /**< 显示SOC */
    WRITE_BT_UINT16(Buffer, index,  Soc_Get());

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x1E4Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp=0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1E4Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1E4Cbk);
    /**< BMS当前充电模式 */
    temp |= (uint16)ChargeConnectM_GetConnectType() << 4 ;
    /**< BMS当前充电状态 */
    if (ChargeM_BatteryChargeIsFinish() == TRUE)
    {
        temp |= ((uint16)2U << 6);  // 充电完成
    }
    else if (RelayM_GetActualStatus(RELAYM_FN_POSITIVE_AC_CHARGE) == RELAYM_ACTUAL_ON)
    {
        temp |= ((uint16)1U << 6);  // 充电中
    }
    WRITE_BT_UINT8(Buffer, index,  (uint8)temp);

    temp = 0U;
    /**< 预充状态 */
    if (PrechargeM_IsFailure() == TRUE)
    {
        temp |= ((uint16)3U);  // 预充失败
    }
    else if(PrechargeM_IsFinish() == TRUE)
    {
        temp |= ((uint16)2U);  // 预充完成
    }
    else if (PrechargeM_IsPrecharging() == TRUE)
    {
        temp |= ((uint16)1U);  // 预充中
    }
    else
    {
    }
    /**< 自检状态 */
    if (Diagnosis_StartDiagIsFinish() == TRUE)
    {
        temp |= ((uint16)1U << 2);  // 自检完成
    }
    else if (Diagnosis_StartDiagIsAllNormal() == FALSE)
    {
        temp |= ((uint16)2U << 2);  // 自检失败
    }
    /**< 均衡状态 */
    if (BalanceM_IsBalance() == TRUE)
    {
        temp |= ((uint16)1U << 4);  // 均衡中
    }
    else
    {
    }
    /**< 加热状态 */
    // temp |= ((uint16)0U << 5);
    /**< 制冷状态 */
    // temp |= ((uint16)0U << 6);
    /**< 高压互锁状态 */
    if (Diagnosis_GetLevel(DIAGNOSIS_ITEM_HVIL_ABNORMAL) == DIAGNOSIS_LEVEL_NONE)
    {
        temp |= ((uint16)1U << 7);  // 互锁中
    }
    else
    {
    }
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    /**< 正极绝缘阻值 */
    temp = Insu_GetPositive();
    if (Insu_ResIsValid(temp) == FALSE)
    {
        temp = 0xFFFFU;
    }
    WRITE_BT_UINT16(Buffer, index, temp);
   
    /**< 负极绝缘阻值 */
    temp = Insu_GetNegative();
    if(Insu_ResIsValid(temp) == FALSE)
    {
        temp = 0xFFFFU;
    }
    WRITE_BT_UINT16(Buffer, index, temp);

    temp = 0U;
    /**< BMS最高报警等级 */
    temp |= (uint16)Diagnosis_GetDiagLevelMax();
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    
    temp = 0U;
    /**< BMS上电Ready信号 */
    if(ChargeM_ChargeIsFault() == E_OK || 
       DischargeM_DischargeIsFault() == E_OK)
    {
        temp |= (uint16)2U;
    }
    else if (ChargeM_ChargeIsReady() == E_OK &&
            DischargeM_DischargeIsAllowed == E_OK)
    {
        temp |= (uint16)1U;
    }
    /**< BMS主从模式 */
    temp |= (uint16)1U << 2;
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x1F5Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    uint8 temp = 0U;
    uint8 goto_flag = 0U;
    Diagnosis_ItemType item;
    Diagnosis_LevelType level = 0U;
    static uint8 this_index;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F5Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F5Cbk);
    /**< 报警码 */
    if (this_index > DIAGNOSIS_ITEM_DEFAULT_NUM) {
        this_index = 0U;
    }
    item = Diagnosis_IndexToItem(this_index);
    item = Diagnosis_GetNextAlarmingItem(item);
    if (item == DIAGNOSIS_ITEM_INVALID_INDEX) {
        if (this_index == 0U) {
            WRITE_BT_UINT8(Buffer, index, 0xFFU);
            goto_flag = 1U;
        } else {
            item = Diagnosis_IndexToItem(0U);
            item = Diagnosis_GetNextAlarmingItem(item);
            if (item == DIAGNOSIS_ITEM_INVALID_INDEX) {
                WRITE_BT_UINT8(Buffer, index, 0xFFU);
                this_index = 0U;
                goto_flag = 1U;
            }
        }
    }
    if (goto_flag == 0U) {
        WRITE_BT_UINT8(Buffer, index, item);
        this_index = Diagnosis_ItemToIndex(item) + 1U;
    }
    /**< 报警等级 */   
    level = Diagnosis_GetLevel(item);
    WRITE_BT_UINT8(Buffer, index, level);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x1F3Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp=0U;
    
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F3Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F3Cbk);
    /**< BMS峰值放电电流 */
    temp = (uint16)PowerM_GetCurrent(POWERM_CUR_DCHARGE_PEAK);
    temp = CURRENT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< BMS持续放电电流 */
    temp = (uint16)PowerM_GetCurrent(POWERM_CUR_DCHARGE_CONTINUE);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< BMS峰值充电电流 */
    temp = (uint16)PowerM_GetCurrent(POWERM_CUR_CHARGE_CONTINUE);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< BMS持续充电电流 */
    temp = (uint16)PowerM_GetCurrent(POWERM_CUR_CHARGE_AC) << 8;
    WRITE_BT_UINT16(Buffer, index, temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x211Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp=0U;
    Insu_ResistorType res;
    App_Tv100mvType volt;
    Current_CurrentType cur;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x211Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x211Cbk);    
    /**< 绝缘电阻 */
    res = Insu_GetSystem();
    if (Insu_ResIsValid(res) == TRUE)
    {
        temp = 0xFFFFU;
    }
    else
    {
        temp |= res << 8;
    }
    WRITE_BT_UINT16(Buffer, index, temp);

    /**< 剩余充电时间 */
    temp = (uint16)Statistic_GetRequireChargeTime();
    WRITE_BT_UINT16(Buffer, index, temp);

    /**< 电池功率 */
    if (RelayM_GetActualStatus(RELAYM_FN_POSITIVE_AC_CHARGE) == RELAYM_ACTUAL_ON)
    {   // 充电
        cur = PowerM_GetCurrent(POWERM_CUR_CHARGE_AC);
        volt = PowerM_GetChargeVoltage(CHARGE_TYPE_AC);
        volt = VOLT_4_DISPLAY(volt);
        if (CurrentM_IsValidCurrent(cur) == TRUE)
        {
            temp = cur*volt / 100000;
        }
    } 
    else if (RelayM_GetActualStatus(RELAYM_FN_POSITIVE_MAIN) == RELAYM_ACTUAL_ON)
    {   // 放电
        cur = PowerM_GetCurrent(POWERM_CUR_DCHARGE_CONTINUE);
        volt = PowerM_GetChargeVoltage(CHARGE_TYPE_AC);
        volt = VOLT_4_DISPLAY(volt);
        if (CurrentM_IsValidCurrent(cur) == TRUE)
        {
            temp = cur*volt / 100000;
        }
    }
    else
    {
        temp = 0U;
    }
    WRITE_BT_UINT16(Buffer, index, temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x351Cbk(uint8 *Buffer, uint16 *Length)
{
    (void)Buffer;
    (void)Length;
    /**< 继电器状态 */
}

void VcuComm_GetMsgData0x352Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x352Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x352Cbk);    
    /**< 最高单体电压 */
    temp = Statistic_GetBcuHvMax();
    temp = VCUCOMM_VOLT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp); 
    /**< 最高单体电压串号 */
    temp = Statistic_GetBcuHvLogicIndex(0U) + 1U;
    if (temp == 0xFFFFU)
    {
        temp = 0U;
    }
    WRITE_BT_UINT16(Buffer, index, temp); 
    /**< 最低单体电压 */
    temp = Statistic_GetBcuLvMax();
    temp = VCUCOMM_VOLT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 最高单体电压串号 */
    temp = Statistic_GetBcuLvLogicIndex(0U) + 1U;
    if (temp == 0xFFFFU)
    {
        temp = 0U;
    }
    WRITE_BT_UINT16(Buffer, index, temp); 

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x353Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;
    
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x353Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x353Cbk);
    /**< 最高温度 */
    temp = Statistic_GetBcuHt(0U);
    temp = TEMP_TO_50_OFFSET(temp);
    temp = TEMP_4_DISPLAY(temp);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 最低温度编号 */
    temp = Statistic_GetBcuHtLogicIndex(0U) + 1U;
    if (temp == 0xFFFFU)
    {
        temp = 0U;
    }
    WRITE_BT_UINT16(Buffer, index, temp); 

    temp = 0U;
    /**< 最低温度 */
    temp = Statistic_GetBcuLt(0U);
    temp = TEMP_TO_50_OFFSET(temp);
    temp = TEMP_4_DISPLAY(temp);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 最低温度编号 */
    temp = Statistic_GetBcuLvLogicIndex(0U) + 1U;
    if (temp == 0xFFFFU)
    {
        temp = 0U;
    }
    WRITE_BT_UINT16(Buffer, index, temp); 

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x354Cbk(uint8 *Buffer, uint16 *Length)
{
    (void)Buffer;
    (void)Length;
    /**< 加热温感最高温度 */
}

void VcuComm_GetMsgData0x355Cbk(uint8 *Buffer, uint16 *Length)
{
    (void)Buffer;
    (void)Length;
    /**< 极柱温感最高温度 */
}

void VcuComm_GetMsgData0x356Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;
    static CellDataM_CellLogicIndexType cell_index = 0U;
    uint8 i;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x356Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x356Cbk);
    /**< 起始单体电压串号 */
    temp = cell_index + 1U;
    WRITE_BT_UINT16(Buffer, index, temp); 
    for (i=0; i<3; i++)
    {
        /**< 起始串号+1单体电压值 */    
        temp = CellDataM_GetVoltage(cell_index+i);
        temp = VCUCOMM_VOLT_4_DISPLAY(temp);
        WRITE_BT_UINT16(Buffer, index, temp); 
    }
    cell_index = cell_index + 1U;
    if (temp == 0xFFFFU)
    {
        temp = 0U;
    }

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x357Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;
    static CellDataM_CellLogicIndexType cell_index = 0U;
    uint8 i;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x357Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x357Cbk);
    /**< 起始单体温度串号 */
    temp = cell_index + 1U;
    WRITE_BT_UINT8(Buffer, index, temp); 
    for (i=0; i<6; i++)
    {
        /**< 起始串号+1温度值 */    
        temp = CellDataM_GetTemperature(cell_index+i);
        temp = TEMP_TO_50_OFFSET(temp);
        temp = TEMP_4_DISPLAY(temp);
        WRITE_BT_UINT8(Buffer, index, (uint8)temp); 
    }
    cell_index = cell_index + 1;
    if (temp == 0xFFFFU)
    {
        temp = 0U;
    }

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x3F3Cbk(uint8 *Buffer, uint16 *Length)
{
    (void)Buffer;
    (void)Length;
    /**< 起始加热温度串号 */
}

void VcuComm_GetMsgData0x3F4Cbk(uint8 *Buffer, uint16 *Length)
{
    (void)Buffer;
    (void)Length;
    /**< 起始极柱温度串号 */
}

void VcuComm_GetMsgData0x3F5Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;
    
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F5Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F5Cbk);
    /**< 累计总放电容量 */
    temp = Soc_GetCumuDchgPower();
    WRITE_BT_UINT32(Buffer, index, temp);
    /**< 累计总充电容量 */
    temp = Soc_GetCumuChgPower();
    WRITE_BT_UINT32(Buffer, index, temp); 

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x3F6Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;
   
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F6Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x3F6Cbk);
    /**< 电池组平均电压 */
    temp = Statistic_GetBcuAverageVoltage();
    temp = VOLT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    
    /**< 电池组平均温度 */
    temp = Statistic_GetBcuAverageTemperature();
    temp = TEMP_TO_50_OFFSET(temp);
    temp = TEMP_4_DISPLAY(temp);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    /**< 电池组最大压差 */
    temp = Statistic_GetBcuDeltaVoltage();
    temp = VOLT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp);

    /**< 电池组最大温差 */
    temp = Statistic_GetBcuDeltaVoltage();
    temp = TEMP_TO_50_OFFSET(temp);
    temp = TEMP_4_DISPLAY(temp);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    /**< 电池组充放电次数 */
    temp = Statistic_GetBcuBatteryDischargeCount();
    WRITE_BT_UINT16(Buffer, index, temp);
        
    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x3FFCbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x3FFCbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x3FFCbk);
    /**< 单体电池串数 */
    temp = BatteryInfo_BaseConfigInfo.SeriesNum;
    WRITE_BT_UINT16(Buffer, index, temp);

    /**< 单体温感个数 */
    temp = BatteryInfo_BaseConfigInfo.CellTemperatureNum;
    WRITE_BT_UINT16(Buffer, index, temp);    

    /**< 极柱温感个数 */
    temp = BatteryInfo_BaseConfigInfo.PoleTemperatureNum;
    WRITE_BT_UINT16(Buffer, index, temp);    

    /**< 加热温感个数 */
    temp = BatteryInfo_BaseConfigInfo.HeatTemperatureNum;
    WRITE_BT_UINT16(Buffer, index, temp);    

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x1F4Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F4Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x1F4Cbk); 
    /**< 最大允许充电电压 */
    temp = UserStrategy_GetChargeVoltMax();
    temp = Statistic_TotalVoltageIsValid(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 最大允许充电电流 */
    temp = UserStrategy_GetChargeCurrentMax();
    temp = CURRENT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    
    temp = 0U;
    /**< 充电控制 */
    if (ChargeM_ChargeIsAllowed())
    {
        temp = 1U;
    }
    WRITE_BT_UINT8(Buffer, index, temp);
    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x201Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x201Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x201Cbk);
    /**< 当前充电电压 */
    temp = PowerM_GetChargeVoltage(CHARGE_TYPE_AC);
    temp = Statistic_TotalVoltageIsValid(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 当前充电电流 */
    temp = PowerM_GetCurrent(POWERM_CUR_CHARGE_AC);
    temp = CURRENT_4_DISPLAY(temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    
    temp = 0U;
    /**< 硬件故障 */
    if (ChargerComm_GetChargerFaultWithIndex(CHARGERCOMM_CHR_HARDWARE_FAULT_INDEX) > 0)
    {
        temp |= (uint8)1U;
    }
    /**< 充电机温度 */
    if (ChargerComm_GetChargerFaultWithIndex(CHARGERCOMM_CHR_OVER_TEMPERATURE_FAULT_INDEX) > 0)
    {
        temp |= (uint8)1U << 1;
    }
    /**< 输入电压 */
    if (ChargerComm_GetChargerFaultWithIndex(CHARGERCOMM_CHR_INPUT_VOLT_FAULT_INDEX) > 0)
    {
        temp |= (uint8)1U << 2;
    }
    /**< 启动状态 */
    if (ChargerComm_GetChargerFaultWithIndex(CHARGERCOMM_CHR_RUN_STATUS_INDEX) > 0)
    {
        temp |= (uint8)1U << 3;
    }
    /**< 通信状态 */
    if (ChargerComm_GetChargerFaultWithIndex(CHARGERCOMM_CHR_COMM_ABORT_WITH_BMS_INDEX) > 0)
    {
        temp |= (uint8)1U << 4;
    }
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x360Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x360Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x360Cbk);
    /**< 继电器总数 */
    temp = RELAYM_FN_NUM;
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    
#ifdef RELAYM_FN_POSITIVE_MAIN
    temp = 0U;    
    /**< 总正继电器状态 */
    if (RelayM_GetActualStatus(RELAYM_FN_POSITIVE_MAIN) == RELAYM_ACTUAL_ON)
    {
        temp |= ((uint8)1U);
    }
    /**< 总正继电器故障状态 */
    if (RelayM_GetDiagnosisStatus(RELAYM_FN_POSITIVE_MAIN) == RELAYM_DIAGNOSIS_ADHESIVE)
    {
        temp |= ((uint8)1U) << 1;
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_POSITIVE_MAIN) == RELAYM_DIAGNOSIS_OPEN_CIRCUIT)
    {
        temp |= ((uint8)2U) << 1;   
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_POSITIVE_MAIN) == RELAYM_DIAGNOSIS_DRIVER_ERR)
    {
        temp |= ((uint8)3U) << 1;   
    }
    /**< 总正继电器索引号 */
    temp |= ((uint8)1U) << 3;  
    WRITE_BT_UINT8(Buffer, index, temp);
#endif


#ifdef RELAYM_FN_PRECHARGE
    temp = 0U;    
    /**< 预充继电器状态 */
    if (RelayM_GetActualStatus(RELAYM_FN_PRECHARGE) == RELAYM_ACTUAL_ON)
    {
        temp |= ((uint8)1U << 1);
    }
    /**< 预充继电器故障状态 */
    if (RelayM_GetDiagnosisStatus(RELAYM_FN_PRECHARGE) == RELAYM_DIAGNOSIS_ADHESIVE)
    {
        temp |= ((uint8)1U) << 1;
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_PRECHARGE) == RELAYM_DIAGNOSIS_OPEN_CIRCUIT)
    {
        temp |= ((uint8)2U) << 1;   
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_PRECHARGE) == RELAYM_DIAGNOSIS_DRIVER_ERR)
    {
        temp |= ((uint8)3U) << 1;   
    }
    /**< 预充继电器索引号 */
    temp |= ((uint8)1U) << 3;  
    WRITE_BT_UINT8(Buffer, index, temp);
#endif


#ifdef RELAYM_FN_POSITIVE_AC_CHARGE
    temp = 0U;    
    /**< 慢充继电器状态 */
    if (RelayM_GetActualStatus(RELAYM_FN_POSITIVE_AC_CHARGE) == RELAYM_ACTUAL_ON)
    {
        temp |= ((uint8)1U << 1);
    }
    /**< 慢充继电器故障状态 */
    if (RelayM_GetDiagnosisStatus(RELAYM_FN_POSITIVE_AC_CHARGE) == RELAYM_DIAGNOSIS_ADHESIVE)
    {
        temp |= ((uint8)1U) << 1;
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_POSITIVE_AC_CHARGE) == RELAYM_DIAGNOSIS_OPEN_CIRCUIT)
    {
        temp |= ((uint8)2U) << 1;   
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_POSITIVE_AC_CHARGE) == RELAYM_DIAGNOSIS_DRIVER_ERR)
    {
        temp |= ((uint8)3U) << 1;   
    }
    /**< 慢充继电器索引号 */
    temp |= ((uint8)1U) << 3;  
    WRITE_BT_UINT8(Buffer, index, temp);    
#endif

#ifdef RELAYM_FN_BUZZER
    temp = 0U;    
    /**< 蜂鸣器继电器状态 */
    if (RelayM_GetActualStatus(RELAYM_FN_BUZZER) == RELAYM_ACTUAL_ON)
    {
        temp |= ((uint8)1U << 1);
    }
    /**< 蜂鸣器继电器故障状态 */
    if (RelayM_GetDiagnosisStatus(RELAYM_FN_BUZZER) == RELAYM_DIAGNOSIS_ADHESIVE)
    {
        temp |= ((uint8)1U) << 1;
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_BUZZER) == RELAYM_DIAGNOSIS_OPEN_CIRCUIT)
    {
        temp |= ((uint8)2U) << 1;   
    }
    else if (RelayM_GetDiagnosisStatus(RELAYM_FN_BUZZER) == RELAYM_DIAGNOSIS_DRIVER_ERR)
    {
        temp |= ((uint8)3U) << 1;   
    }
    /**< 蜂鸣器继电器索引号 */
    temp |= ((uint8)1U) << 3;  
    WRITE_BT_UINT8(Buffer, index, temp);    
#endif

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x361Cbk(uint8 *Buffer, uint16 *Length)
{
    (void)Buffer;
    (void)Length;
    /**< 继电器状态 */
}

void VcuComm_GetMsgData0x358Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    uint8 temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x358Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x358Cbk);
    /**< 电池最高单体电压从机号 */
    temp = Statistic_GetBcuHvSlaveNum(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 电池最高单体电压从机串号 */
    temp = Statistic_GetBcuHvIndex(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 电池最低单体电压从机号 */
    temp = Statistic_GetBcuLvSlaveNum(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 电池最低单体电压从机串号 */
    temp = Statistic_GetBcuLvIndex(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    /**< 电池最高温度从机号 */
    temp = Statistic_GetBcuHtSlaveNum(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 电池最高温度从机串号 */
    temp = Statistic_GetBcuHtIndex(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 电池最低温度从机号 */
    temp = Statistic_GetBcuLtSlaveNum(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);
    /**< 电池最低温度从机串号 */
    temp = Statistic_GetBcuLtIndex(0U);
    WRITE_BT_UINT8(Buffer, index, (uint8)temp);

    *Length = index; 
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif  
}

void VcuComm_GetMsgData0x202Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x202Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x202Cbk);
    /**< 年 */
    WRITE_BT_UINT16(Buffer, index, (uint16)APP_INFO_BUILD_DATE_Y);
    /**< 月 */
    WRITE_BT_UINT8(Buffer, index, (uint8)APP_INFO_BUILD_DATE_M);
    /**< 日 */
    WRITE_BT_UINT8(Buffer, index, (uint8)APP_INFO_BUILD_DATE_D);
    /**< 时 */
    WRITE_BT_UINT8(Buffer, index, (uint8)APP_INFO_BUILD_TIME_H);
    /**< 分 */
    WRITE_BT_UINT8(Buffer, index, (uint8)APP_INFO_BUILD_TIME_M);
    /**< 秒 */
    WRITE_BT_UINT8(Buffer, index, (uint8)APP_INFO_BUILD_TIME_S);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x203Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    uint32 temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x203Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x203Cbk);
    /**< 累计总放电时间 */
    temp = S_TO_HOUR(Statistic_GetCumuDchgTime()) * 10;
    WRITE_BT_UINT32(Buffer, index, temp);
    /**< 累计总放电时间 */
    temp = S_TO_HOUR(Statistic_GetCumuChgTime()) * 10;
    WRITE_BT_UINT32(Buffer, index, temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x204Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    uint32 temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x204Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x204Cbk);
    /**< 累计总使用时间 */
    temp = Statistic_GetCumuDchgTime() + Statistic_GetCumuChgTime();
    temp =  S_TO_HOUR(temp) * 10;
    WRITE_BT_UINT32(Buffer, index, temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x205Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x205Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x205Cbk);
    /**< 电池总容量 */
    (void)ParameterM_EeepRead(PARAMETERM_EEEP_TOTAL_CAP_INDEX, &temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 电池组剩余容量 */
    (void)ParameterM_EeepRead(PARAMETERM_EEEP_LEFT_CAP_INDEX, &temp);
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< 已充电时间 */
    temp = S_TO_MIN(ChargerComm_GetChargerChargedTime());
    WRITE_BT_UINT16(Buffer, index, temp);
    /**< SOH */
    temp = Soh_Get();
    WRITE_BT_UINT16(Buffer, index, temp);

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x206Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    uint8 temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x206Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x206Cbk);
    /**< SOC满诊断校准自诊断 */
    temp = (uint8)SocDiagCalib_GetFullReason();
    WRITE_BT_UINT8(Buffer, index, temp);  
    /**< SOC空诊断校准自诊断 */
    temp = (uint8)SocDiagCalib_GetEmptyReason();
    WRITE_BT_UINT8(Buffer, index, temp);  
    /**< 放电自检故障 */
    temp = (uint8)DischargeM_GetStartDiagFault();
    WRITE_BT_UINT8(Buffer, index, temp);   
    /**< 放电诊断故障标志 */
    temp = (uint8)DischargeM_GetDiagFaultFlag();
    WRITE_BT_UINT8(Buffer, index, temp);   
    /**< 放电诊断故障动作 */
    temp = (uint8)DischargeM_GetDiagFaultAction();  
    WRITE_BT_UINT8(Buffer, index, temp);   
    /**< 放电其他故障 */
    temp = DischargeM_GetOthersFault();
    WRITE_BT_UINT8(Buffer, index, temp); 

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x207Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index = 0U;
    uint16 temp = 0U;
    Diagnosis_ItemType item;
    ChargeM_OthersFaultIndexType otherItem;
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x206Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x206Cbk);
    /**< 充充电自检故障 */
    item = ChargeM_GetStartDiagFault();
    WRITE_BT_UINT8(Buffer, index, (uint8)temp); 
    /**< 充电诊断故障标志 */
    item = ChargeM_GetDiagFaultFlag();
    WRITE_BT_UINT8(Buffer, index, (uint8)temp); 
    /**< 充电诊断故障动作 */
    item = ChargeM_GetDiagFaultAction();
    WRITE_BT_UINT8(Buffer, index, (uint8)temp); 
    /**< 充电其他故障 */
    otherItem = ChargeM_GetOthersFault();
    WRITE_BT_UINT8(Buffer, index, otherItem); 
    /**< 充电其他故障 */
    temp = ChargeM_GetChargerGBReadyFault();
    WRITE_BT_UINT16(Buffer, index, otherItem); 

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x208Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, temp = 0U;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x208Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x208Cbk);
    /**< 蜂鸣器控制 */
    if (RelayM_GetActualStatus(RELAYM_FN_BUZZER) == RELAYM_ACTUAL_ON)
    {
        temp = (uint16)1U;
    }
    WRITE_BT_UINT8(Buffer, index, temp); 

    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x390Cbk(uint8 *Buffer, uint16 *Length)
{
    uint16 index, length = 0U;
    uint8  temp = 0;

    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_GetMsgData0x390Cbk);
    VALIDATE_PTR(Length, VCUCOMM_MESSAGES_API_ID_GetMsgData0x390Cbk);
    /**< 主机HWID获取 */
    DeviceInfo_GetHWID(DEVICE_TYPE_C600, &temp, &length);
    WRITE_BT_UINT8(Buffer, index, temp); 
    *Length = index;
#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
}

void VcuComm_GetMsgData0x391Cbk(uint8 *Buffer, uint16 *Length)
{

}

void VcuComm_ReceiveCbk(uint8 *Buffer, uint16 Length)
{
    uint16 index = 0U;
    uint8 vcuCommand = 0U;
    VALIDATE_PTR(Buffer, VCUCOMM_MESSAGES_API_ID_ReceiveCbk);

    VcuComm_SetCommunicationStatus(TRUE);
    VcuComm_ClrCommAbortMessageFlag((uint16)VCUCOMM_RX_IPDU_MSG_0x160);
    vcuCommand = READ_BT_UINT8(Buffer, index);
    
    /**< VCU高压上电命令 */
    if (vcuCommand & 0x01)
    {
        VcuComm_MsgData.PowerCommand = VCUCOMM_POWER_ON;
    }
    else
    {
        VcuComm_MsgData.PowerCommand = VCUCOMM_POWER_OFF;
    }
    /**< VCU紧急下电命令 */
    if (vcuCommand & 0x02)
    {
        VcuComm_MsgData.PowerCommand = VCUCOMM_POWER_OFF;
    }

#if ( VCUCOMM_DEV_ERROR_DETECT == STD_ON )
cleanup:
#endif
    return;
}

void VcuComm_RecTimeoutCbk(void)
{
    VcuComm_MsgData.PowerCommand = VCUCOMM_POWER_OFF;
    VcuComm_SetCommunicationStatus(FALSE);
    VcuComm_SetCommAbortMessageFlag((uint16)VCUCOMM_RX_IPDU_MSG_0x160);
}


// Condition Check function define
Std_ReturnType VcuComm_SendConditionCheck(uint16 IPdu)
{
    Std_ReturnType res = E_NOT_OK;

    (void)IPdu;
    if (VcuComm_GetCurrentRecStage() == (uint16)VCUCOMM_STAGE_STAGE1)
    {
        res = E_OK;
    }
    return res;
}

Std_ReturnType VcuComm_RecConditionCheck(void)
{
    Std_ReturnType res = E_NOT_OK;
    uint16 stage;

    stage = VcuComm_GetCurrentRecStage();
    if (stage == (uint16)VCUCOMM_STAGE_STAGE1)
    {
        res = E_OK;
    }
    return res;
}

static uint16 VcuComm_bms2VcuCurrent(Current_CurrentType current)
{
    uint16 vcu_current;
    Current_CurrentType cur_offset = VCUCOMM_CURRENT_OFFSET;

    if (!CurrentM_IsValidCurrent(current))
    {
        current = 0;
    }
    if (current < (-1) * cur_offset)
    {
        vcu_current = 0U;
    }
    else if (current > cur_offset)
    {
        vcu_current = (uint16)cur_offset * 2U;
    }
    else
    {
        vcu_current = (uint16)current + (uint16)cur_offset;
    }
    return vcu_current;
}

